// Copyright 2020 Christian Nilsson

#include "ir_Corona.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"

// Tests for decodeCoronaAc().
TEST(TestDecodeCoronaAc, RealExample) {
  IRsendTest irsend(kGpioUnused);
  IRrecv irrecv(kGpioUnused);

  const uint16_t rawData_On[347] = {
      3520, 1686,
      460, 386,  452, 454,  408, 452,  410, 1320, 434, 428,  434, 1296,
      410, 452,  490, 374,  438, 1292, 434, 430,  434, 428,  438, 424,
      438, 426,  438, 1266, 464, 1266, 462, 402,  462, 1266, 464, 400,
      462, 1268, 464, 1266, 462, 1266, 464, 1268, 486, 376,  462, 402,
      472, 1256, 488, 378,  514, 346,  464, 1266, 488, 1240, 462, 404,
      462, 426,  460, 376,  462, 402,  488, 1240, 464, 1266, 462, 402,
      462, 400,  490, 1240, 462, 1266, 486, 1244, 460, 1268, 462, 1266,
      462, 1266, 462, 404,  458, 1270, 458, 1268, 462, 400,  464, 428,
      434, 402,  460, 402,  462, 398,  462, 1268, 462, 404,  460, 402,
      460, 1266, 466, 1264,
      462, 10808,
      3502, 1686,
      462, 400,  462, 400,  462, 400,  464, 1266, 462, 404,  458, 1266,
      464, 402,  460, 402,  462, 1266, 464, 404,  458, 402,  460, 400,
      488, 374,  464, 1266, 462, 1266, 466, 398,  462, 1268, 462, 400,
      518, 1208, 438, 1292, 440, 426,  488, 1242, 466, 1264, 460, 402,
      490, 1238, 490, 1238, 490, 1242, 514, 1212, 464, 1268, 490, 1238,
      464, 1266, 490, 1238, 462, 406,  458, 400,  464, 398,  464, 402,
      488, 374,  486, 376,  460, 402,  488, 372,  464, 1268, 462, 1264,
      464, 1266, 462, 1268, 462, 1266, 466, 1266, 490, 1242, 458, 1264,
      516, 348,  462, 404,  460, 404,  462, 398,  516, 344,  462, 400,
      464, 402,  488, 376,
      460, 10810,
      3526, 1658,
      462, 404,  460, 400,  488, 374,  464, 1264, 462, 402,  464, 1266,
      462, 402,  486, 374,  462, 1266, 546, 318,  462, 400,  464, 400,
      462, 402,  460, 1268, 466, 1262, 492, 374,  516, 1212, 464, 400,
      462, 1266, 516, 1212, 464, 402,  462, 424,  462, 1242, 460, 1268,
      488, 1242, 462, 1268, 490, 1236, 466, 1264, 462, 1268, 464, 1266,
      460, 1268, 464, 1266, 462, 338,  528, 402,  486, 374,  462, 402,
      460, 402,  490, 374,  458, 406,  458, 402,  488, 1240, 490, 1238,
      462, 1268, 464, 1268, 490, 1238, 488, 1242, 462, 1264, 464, 1270,
      462, 398,  436, 426,  460, 406,  458, 404,  434, 424,  464, 400,
      462, 400,  460, 402,
      462};  // UNKNOWN 94D81276 * ON
  const uint8_t expectedState_On[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x37, 0xC8,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_On, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_On, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: On, Mode: 0 (Heat), Temp: 23C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_Off[347] = {
      3520, 1686,
      462, 400,  460, 402,  462, 382,  482, 1266, 462, 400,  462, 1268,
      462, 404,  488, 372,  462, 1266, 464, 402,  458, 404,  458, 382,
      482, 400,  462, 1266, 438, 1294, 488, 376,  460, 1268, 460, 400,
      470, 1260, 460, 1270, 462, 1268, 460, 1268, 462, 404,  458, 402,
      460, 1266, 462, 402,  462, 400,  462, 1268, 464, 1264, 462, 384,
      480, 400,  460, 404,  448, 414,  460, 1268, 462, 1268, 460, 402,
      490, 372,  462, 1268, 464, 1266, 462, 1268, 460, 1266, 464, 1266,
      464, 1266, 462, 404,  460, 400,  438, 1294, 486, 376,  462, 400,
      462, 402,  462, 400,  460, 402,  462, 1268, 460, 1268, 462, 404,
      486, 1240, 464, 1268,
      460, 10788,
      3524, 1682,
      462, 402,  462, 402,  460, 404,  460, 1266, 490, 374,  460, 1268,
      464, 400,  460, 406,  460, 1268, 464, 400,  458, 402,  462, 404,
      458, 404,  460, 1268, 460, 1268, 464, 400,  466, 1268, 456, 404,
      460, 1268, 460, 1268, 462, 402,  462, 1268, 462, 1266, 462, 402,
      462, 1268, 462, 1266, 488, 1242, 462, 1264, 460, 1270, 462, 1266,
      464, 1264, 462, 1270, 460, 402,  462, 402,  462, 400,  460, 402,
      462, 402,  462, 400,  462, 400,  460, 402,  462, 1266, 462, 1266,
      460, 1270, 462, 1268, 462, 1266, 460, 1268, 462, 1268, 462, 1268,
      462, 400,  458, 404,  466, 396,  436, 428,  460, 402,  460, 404,
      460, 402,  436, 428,
      462, 10794,
      3520, 1682,
      490, 376,  460, 402,  462, 402,  462, 1266, 462, 400,  462, 1268,
      460, 402,  460, 400,  462, 1266, 464, 400,  460, 402,  488, 378,
      456, 384,  482, 1268, 460, 1268, 462, 402,  460, 1268, 460, 404,
      460, 1268, 436, 1276, 480, 404,  456, 404,  460, 1268, 462, 1268,
      460, 1268, 462, 1270, 462, 1268, 462, 1268, 462, 1266, 460, 1268,
      462, 1268, 462, 1268, 462, 400,  462, 384,  478, 404,  460, 384,
      480, 400,  488, 376,  460, 404,  458, 404,  460, 1268, 464, 1264,
      462, 1268, 462, 1268, 462, 1270, 462, 1268, 486, 1244, 460, 1266,
      462, 400,  462, 400,  462, 402,  460, 404,  460, 400,  460, 404,
      486, 374,  462, 400,
      464};  // UNKNOWN A37A38D7 * Off
  const uint8_t expectedState_Off[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x27, 0xD8,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_Off, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_Off, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: Off, Power Button: On, Mode: 0 (Heat), Temp: 23C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_17C[347] = {
      3522, 1686,
      458, 404,  486, 374,  434, 432,  482, 1244, 462, 400,  460, 1268,
      462, 400,  462, 386,  478, 1268, 462, 402,  462, 404,  458, 400,
      464, 400,  462, 1272, 456, 1268, 460, 402,  460, 1270, 434, 428,
      462, 1268, 460, 1268, 464, 1268, 460, 1266, 462, 402,  460, 382,
      482, 1264, 464, 400,  462, 402,  460, 1268, 460, 1270, 462, 404,
      460, 400,  460, 402,  462, 382,  506, 1242, 462, 1268, 464, 398,
      460, 398,  466, 1268, 458, 1268, 462, 1266, 462, 1266, 462, 402,
      458, 406,  460, 402,  460, 1270, 460, 406,  432, 428,  462, 402,
      438, 424,  460, 1268, 462, 1270, 460, 1266, 462, 402,  462, 1266,
      462, 1270, 460, 1268,
      438, 10814,
      3522, 1684,
      462, 402,  464, 402,  460, 400,  462, 1266, 462, 400,  462, 1266,
      466, 398,  462, 402,  460, 1270, 460, 384,  478, 402,  434, 428,
      462, 402,  516, 1212, 436, 1294, 460, 402,  460, 1268, 464, 400,
      460, 1268, 462, 1268, 434, 428,  462, 1266, 462, 1266, 462, 400,
      460, 1270, 462, 1268, 458, 1268, 436, 1274, 480, 1268, 460, 1266,
      490, 1240, 462, 1268, 460, 404,  460, 402,  488, 376,  462, 402,
      460, 402,  492, 370,  462, 400,  464, 402,  458, 1268, 490, 1240,
      460, 1268, 464, 1266, 462, 1266, 460, 1272, 460, 1266, 462, 1266,
      464, 400,  462, 404,  462, 400,  462, 402,  458, 384,  480, 402,
      458, 402,  460, 402,
      464, 10810,
      3528, 1660,
      490, 374,  462, 404,  458, 400,  462, 1268, 460, 404,  460, 1270,
      458, 402,  460, 402,  462, 1266, 486, 378,  460, 382,  506, 376,
      458, 404,  460, 1270, 460, 1270, 460, 402,  460, 1268, 464, 402,
      456, 1268, 462, 1268, 462, 402,  460, 402,  462, 1266, 462, 1266,
      464, 1266, 460, 1272, 460, 1266, 464, 1266, 462, 1266, 462, 1268,
      462, 1266, 462, 1268, 462, 402,  460, 404,  462, 402,  512, 352,
      512, 346,  438, 426,  462, 402,  460, 400,  462, 1268, 462, 1268,
      462, 1268, 460, 1270, 434, 1292, 464, 1266, 462, 1268, 460, 1270,
      514, 350,  432, 430,  460, 402,  460, 404,  460, 384,  480, 400,
      490, 374,  458, 404,
      462};  // UNKNOWN 8CC3C997 * 17C
  const uint8_t expectedState_17C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x11, 0xEE,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_17C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_17C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 17C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_18C[347] = {
      3520, 1686,
      462, 400,  460, 402,  436, 426,  488, 1242, 460, 402,  460, 1270,
      460, 404,  462, 398,  462, 1268, 462, 402,  462, 402,  436, 326,
      536, 430,  458, 1266, 462, 1268, 486, 380,  456, 1270, 462, 400,
      462, 1268, 462, 1266, 490, 1240, 438, 1292, 462, 404,  462, 400,
      462, 1266, 460, 404,  458, 404,  484, 1244, 466, 1264, 460, 402,
      436, 430,  458, 400,  436, 426,  460, 1268, 462, 1268, 438, 426,
      434, 428,  462, 1268, 462, 1266, 464, 1266, 462, 428,  436, 1268,
      436, 406,  480, 402,  462, 1270, 458, 404,  460, 402,  488, 374,
      464, 1246, 480, 400,  436, 1292, 488, 1242, 462, 402,  460, 1268,
      462, 1250, 480, 1268,
      462, 10790,
      3520, 1684,
      464, 402,  460, 404,  462, 398,  462, 1266, 464, 400,  462, 1270,
      460, 402,  458, 406,  456, 1268, 436, 424,  464, 400,  460, 404,
      462, 400,  462, 1268, 462, 1268, 464, 398,  488, 1238, 464, 400,
      462, 1268, 462, 1248, 478, 384,  482, 1264, 436, 1292, 462, 402,
      462, 1266, 464, 1266, 460, 1268, 464, 1268, 462, 1266, 462, 1266,
      464, 1266, 462, 1268, 462, 402,  486, 376,  464, 398,  460, 404,
      462, 402,  436, 426,  462, 428,  408, 428,  460, 1268, 460, 1268,
      436, 1290, 466, 1264, 464, 1266, 460, 1270, 462, 1264, 462, 1268,
      460, 404,  462, 402,  460, 400,  462, 404,  458, 404,  460, 404,
      460, 382,  482, 400,
      460, 10812,
      3480, 1706,
      464, 402,  482, 376,  460, 404,  458, 1270, 462, 402,  462, 1268,
      462, 400,  460, 402,  462, 1268, 462, 400,  462, 400,  464, 400,
      436, 426,  436, 1294, 462, 1268, 462, 402,  516, 1212, 462, 402,
      464, 1266, 460, 1266, 438, 428,  460, 402,  460, 1268, 462, 1268,
      488, 1242, 462, 1264, 460, 1270, 462, 1266, 462, 1266, 462, 1268,
      462, 1268, 460, 1270, 462, 400,  462, 402,  460, 400,  462, 400,
      488, 378,  458, 402,  462, 400,  516, 348,  460, 1268, 436, 1276,
      478, 1268, 436, 1292, 462, 1270, 460, 1268, 462, 1248, 484, 1266,
      460, 400,  464, 402,  460, 404,  432, 426,  436, 430,  462, 400,
      432, 428,  434, 426,
      464};  // UNKNOWN 513BFA3A * 18C
  const uint8_t expectedState_18C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x12, 0xED,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_18C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_18C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 18C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_19C[347] = {
      3508, 1682,
      490, 350,  488, 372,  514, 372,  466, 1262, 468, 398,  464, 1262,
      466, 396,  466, 396,  496, 1234, 442, 400,  488, 396,  470, 396,
      464, 396,  466, 1262, 468, 1260, 466, 396,  468, 1262, 466, 396,
      520, 1210, 474, 1254, 470, 1260, 466, 1266, 464, 396,  494, 368,
      468, 1260, 468, 364,  498, 396,  466, 1264, 470, 1260, 466, 394,
      466, 398,  468, 392,  494, 370,  466, 1262, 524, 1206, 466, 398,
      466, 396,  520, 1210, 492, 1238, 464, 1268, 466, 1260, 492, 1236,
      494, 350,  484, 398,  466, 1262, 468, 1264, 466, 396,  468, 396,
      492, 350,  486, 398,  466, 1262, 494, 1236, 466, 394,  468, 396,
      492, 1236, 494, 1236,
      466, 10804,
      3508, 1680,
      466, 292,  572, 396,  464, 396,  466, 1262, 466, 398,  466, 1264,
      468, 374,  488, 296,  568, 1262, 464, 396,  524, 288,  520, 396,
      468, 396,  492, 1234, 466, 1266, 464, 398,  464, 1262, 468, 398,
      492, 1234, 468, 1262, 466, 396,  442, 1286, 468, 1264, 466, 394,
      468, 1264, 518, 1210, 492, 1238, 466, 1264, 520, 1206, 468, 1262,
      468, 1260, 472, 1260, 466, 394,  468, 396,  494, 348,  488, 376,
      484, 396,  470, 396,  464, 396,  494, 346,  492, 1260, 468, 1262,
      468, 1262, 492, 1236, 494, 1236, 492, 1236, 466, 1262, 468, 1262,
      468, 394,  466, 398,  492, 370,  466, 396,  468, 394,  496, 368,
      492, 370,  466, 398,
      490, 10780,
      3510, 1680,
      468, 374,  486, 396,  494, 348,  486, 1264, 492, 368,  492, 1236,
      468, 398,  466, 394,  468, 1262, 464, 304,  536, 402,  512, 370,
      492, 370,  492, 1236, 468, 1262, 468, 394,  492, 1238, 466, 398,
      466, 1264, 468, 1262, 490, 372,  492, 290,  546, 1262, 522, 1208,
      466, 1264, 466, 1264, 468, 1258, 494, 1236, 468, 1264, 466, 1264,
      520, 1208, 494, 1238, 494, 370,  466, 396,  464, 396,  520, 292,
      518, 394,  468, 398,  464, 376,  490, 394,  468, 1264, 464, 1264,
      466, 1260, 466, 1264, 496, 1232, 466, 1262, 468, 1262, 466, 1264,
      466, 396,  492, 372,  468, 374,  486, 398,  464, 396,  468, 398,
      464, 398,  466, 396,
      464};  // CORONA_AC * On 19C
  const uint8_t expectedState_19C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x33, 0xCC,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_19C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_19C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: On, Mode: 0 (Heat), Temp: 19C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_20C[347] = {
      3522, 1684,
      466, 398,  462, 402,  462, 382,  480, 1266, 460, 404,  462, 1266,
      464, 400,  464, 398,  462, 1268, 462, 400,  462, 404,  460, 402,
      458, 402,  466, 1266, 434, 1292, 462, 402,  460, 1268, 460, 386,
      478, 1266, 462, 1268, 460, 1268, 460, 1268, 462, 404,  460, 402,
      462, 1266, 462, 384,  480, 404,  460, 1268, 436, 1294, 460, 402,
      462, 400,  464, 402,  456, 406,  460, 1268, 464, 1264, 468, 398,
      460, 402,  460, 1270, 488, 1240, 460, 1270, 434, 430,  458, 402,
      458, 1270, 462, 402,  462, 1268, 462, 400,  462, 400,  462, 402,
      462, 1266, 464, 1264, 462, 404,  432, 1296, 438, 426,  462, 1268,
      458, 1270, 460, 1268,
      464, 10788,
      3518, 1686,
      488, 376,  462, 400,  462, 402,  460, 1268, 436, 426,  438, 1292,
      462, 402,  518, 344,  462, 1266, 462, 400,  460, 402,  436, 428,
      460, 402,  458, 1268, 438, 1292, 438, 424,  464, 1266, 460, 404,
      460, 1266, 462, 1268, 462, 400,  462, 1268, 462, 1266, 462, 400,
      462, 1268, 462, 1268, 464, 1264, 462, 1266, 460, 1270, 486, 1242,
      462, 1268, 436, 1294, 508, 292,  526, 400,  462, 402,  460, 402,
      488, 374,  462, 404,  436, 424,  462, 402,  438, 1292, 460, 1266,
      462, 1268, 460, 1266, 464, 1268, 460, 1268, 436, 1294, 490, 1240,
      434, 428,  438, 424,  460, 404,  436, 426,  462, 404,  484, 374,
      462, 404,  462, 400,
      460, 10792,
      3546, 1658,
      436, 430,  460, 400,  462, 404,  460, 1266, 462, 402,  438, 1292,
      462, 402,  458, 404,  436, 1290, 494, 374,  460, 402,  460, 402,
      462, 398,  436, 1292, 462, 1268, 462, 402,  436, 1290, 464, 400,
      462, 1266, 438, 1292, 462, 402,  490, 374,  434, 1296, 432, 1298,
      432, 1292, 464, 1266, 460, 1268, 462, 1268, 490, 1240, 436, 1292,
      464, 1266, 438, 1290, 462, 402,  436, 426,  462, 400,  460, 402,
      460, 402,  436, 426,  488, 374,  436, 428,  460, 1270, 462, 1268,
      462, 1268, 436, 1292, 462, 1266, 462, 1268, 460, 1266, 462, 1268,
      460, 406,  458, 402,  462, 402,  436, 408,  482, 400,  438, 426,
      434, 428,  460, 404,
      434};  // UNKNOWN 48F17976 * 20C
  const uint8_t expectedState_20C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x14, 0xEB,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_20C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_20C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 20C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_21C[347] = {
      3522, 1684,
      434, 430,  430, 412,  460, 418,  462, 1268, 460, 386,  452, 1296,
      460, 426,  432, 386,  480, 1268, 458, 404,  432, 430,  434, 428,
      434, 428,  460, 1266, 490, 1240, 462, 402,  460, 1268, 460, 386,
      452, 1296, 458, 1272, 460, 1266, 462, 1270, 460, 404,  434, 428,
      458, 1270, 434, 430,  432, 430,  460, 1268, 462, 1270, 458, 430,
      406, 432,  456, 404,  458, 404,  466, 1262, 460, 1270, 458, 406,
      456, 406,  458, 1268, 460, 1270, 488, 1240, 490, 1240, 460, 384,
      478, 1268, 436, 430,  432, 1294, 462, 384,  450, 456,  432, 404,
      436, 430,  458, 1270, 434, 430,  460, 1268, 460, 404,  464, 1264,
      460, 1268, 460, 1270,
      460, 10808,
      3504, 1682,
      462, 402,  460, 430,  430, 406,  460, 1268, 462, 428,  436, 1268,
      434, 432,  458, 404,  458, 1272, 458, 426,  432, 406,  460, 404,
      460, 428,  406, 1296, 462, 1268, 434, 454,  408, 1278, 480, 426,
      408, 1294, 460, 1268, 460, 404,  432, 1294, 462, 1268, 458, 384,
      480, 1272, 460, 1266, 460, 1270, 460, 1268, 462, 1266, 462, 1268,
      460, 1268, 462, 1268, 436, 428,  436, 428,  464, 424,  434, 386,
      478, 428,  434, 406,  432, 410,  478, 386,  476, 1270, 462, 1270,
      462, 1266, 460, 1270, 458, 1272, 458, 1270, 436, 1292, 464, 1266,
      434, 430,  460, 428,  408, 430,  458, 404,  484, 378,  432, 430,
      460, 404,  458, 406,
      458, 10796,
      3542, 1662,
      460, 402,  434, 456,  430, 406,  458, 1270, 458, 408,  432, 1294,
      462, 382,  480, 384,  450, 1296, 488, 374,  458, 406,  432, 430,
      432, 456,  432, 1270, 436, 1292, 462, 402,  434, 1294, 434, 428,
      460, 1268, 460, 1270, 458, 402,  464, 400,  462, 1266, 460, 1270,
      460, 1270, 434, 1294, 464, 1268, 486, 1242, 464, 1266, 460, 1270,
      486, 1244, 458, 1268, 464, 402,  458, 402,  460, 404,  434, 452,
      410, 428,  432, 432,  456, 432,  408, 426,  462, 1268, 462, 1268,
      434, 1296, 462, 1268, 458, 1270, 466, 1262, 464, 1272, 456, 1268,
      460, 406,  458, 402,  460, 404,  460, 404,  460, 402,  458, 430,
      430, 386,  480, 402,
      460};  // UNKNOWN D1869C5B * 21C
  const uint8_t expectedState_21C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x15, 0xEA,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_21C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_21C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 21C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_22C[347] = {
      3524, 1686,
      460, 404,  458, 402,  462, 400,  462, 1248, 482, 400,  460, 1268,
      436, 428,  488, 374,  460, 1268, 460, 404,  460, 402,  462, 402,
      460, 402,  462, 1268, 458, 1270, 458, 404,  460, 1248, 480, 402,
      462, 1268, 436, 1292, 462, 1270, 460, 1268, 462, 400,  460, 402,
      462, 1266, 460, 404,  436, 428,  462, 1266, 462, 1268, 460, 402,
      462, 402,  460, 404,  434, 428,  462, 1266, 438, 1290, 462, 404,
      460, 404,  434, 1292, 466, 1266, 436, 1294, 462, 400,  462, 1268,
      436, 1294, 460, 402,  462, 1268, 436, 426,  492, 374,  458, 400,
      464, 1266, 462, 400,  436, 428,  460, 1266, 492, 372,  462, 1268,
      460, 1268, 462, 1268,
      488, 10762,
      3496, 1710,
      462, 400,  462, 400,  460, 402,  460, 1270, 434, 426,  462, 1268,
      460, 400,  438, 424,  438, 1292, 436, 426,  460, 402,  436, 426,
      438, 426,  460, 1268, 464, 1266, 462, 400,  462, 1268, 464, 400,
      434, 1294, 464, 1268, 488, 372,  462, 1268, 464, 1264, 436, 426,
      490, 1240, 438, 1292, 464, 1264, 460, 1270, 436, 1294, 460, 1268,
      434, 1294, 462, 1266, 438, 426,  460, 402,  462, 400,  462, 402,
      462, 400,  460, 402,  462, 402,  460, 382,  482, 1268, 436, 1294,
      462, 1266, 436, 1294, 460, 1268, 438, 1290, 462, 1268, 462, 1268,
      462, 400,  462, 400,  464, 400,  462, 402,  462, 400,  488, 372,
      492, 372,  460, 402,
      460, 10810,
      3528, 1660,
      462, 404,  434, 426,  464, 400,  434, 1294, 462, 400,  464, 1266,
      462, 400,  464, 398,  466, 1264, 462, 402,  460, 402,  464, 398,
      464, 398,  462, 1268, 462, 1266, 440, 422,  462, 1268, 462, 404,
      462, 1264, 436, 1294, 460, 402,  462, 400,  438, 1292, 464, 1266,
      460, 1268, 462, 1266, 464, 1268, 462, 1266, 462, 1266, 462, 1266,
      438, 1292, 464, 1266, 460, 400,  462, 384,  480, 402,  460, 404,
      434, 428,  462, 402,  434, 428,  460, 402,  458, 1270, 462, 1266,
      464, 1266, 464, 1266, 464, 1264, 464, 1266, 462, 1246, 484, 1266,
      438, 424,  438, 424,  462, 402,  462, 400,  438, 424,  460, 402,
      462, 400,  436, 428,
      434};  // UNKNOWN 21DD90BB * 22C
  const uint8_t expectedState_22C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x16, 0xE9,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_22C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_22C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 22C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_23C[347] = {
      3522, 1684,
      460, 402,  462, 428,  406, 430,  458, 1270, 462, 400,  460, 1268,
      462, 402,  462, 402,  462, 1266, 462, 404,  432, 428,  434, 428,
      462, 402,  458, 1266, 464, 1268, 458, 402,  516, 1216, 460, 404,
      458, 1268, 462, 1268, 462, 1266, 462, 1266, 462, 402,  460, 406,
      456, 1268, 462, 402,  460, 402,  462, 1268, 462, 1266, 462, 402,
      460, 402,  488, 374,  490, 398,  434, 1270, 460, 1268, 460, 404,
      460, 430,  408, 1292, 462, 1268, 462, 1266, 462, 1268, 460, 1250,
      506, 1242, 462, 400,  460, 1268, 462, 400,  460, 408,  456, 404,
      458, 404,  460, 398,  462, 404,  458, 1268, 434, 430,  460, 1268,
      462, 1266, 462, 1268,
      464, 10790,
      3520, 1682,
      464, 402,  460, 428,  406, 430,  458, 1270, 462, 402,  460, 1268,
      462, 406,  488, 374,  430, 1296, 460, 402,  462, 402,  462, 400,
      462, 402,  458, 1268, 490, 1242, 460, 402,  460, 1272, 460, 400,
      460, 1268, 462, 1266, 462, 404,  462, 1264, 462, 1266, 490, 374,
      464, 1268, 458, 1268, 492, 1236, 462, 1266, 464, 1264, 462, 1250,
      478, 1266, 462, 1268, 462, 402,  460, 384,  478, 402,  434, 428,
      460, 404,  460, 402,  462, 400,  460, 430,  430, 1270, 490, 1240,
      460, 1268, 462, 1268, 460, 1272, 460, 1268, 436, 1294, 462, 1264,
      464, 400,  460, 386,  504, 400,  434, 404,  460, 402,  462, 384,
      476, 384,  454, 426,
      462, 10792,
      3548, 1656,
      462, 404,  460, 400,  516, 350,  458, 1268, 462, 400,  434, 1294,
      464, 424,  434, 382,  480, 1270, 462, 406,  454, 406,  458, 402,
      462, 402,  434, 1294, 514, 1216, 462, 400,  434, 1298, 458, 404,
      460, 1268, 460, 1270, 460, 402,  464, 398,  460, 1268, 464, 1266,
      436, 1294, 460, 1268, 460, 1270, 462, 1264, 436, 1292, 462, 1268,
      436, 1294, 460, 1268, 460, 402,  460, 402,  486, 376,  462, 402,
      460, 402,  462, 428,  408, 430,  464, 426,  430, 1272, 460, 1270,
      462, 1268, 434, 1292, 462, 1268, 464, 1266, 464, 1268, 462, 1266,
      464, 402,  458, 432,  434, 402,  434, 430,  488, 398,  410, 428,
      460, 402,  460, 428,
      410};  // UNKNOWN F68FE737 * 23C
  const uint8_t expectedState_23C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x17, 0xE8,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_23C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_23C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 23C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_24C[347] = {
      3522, 1686,
      460, 428,  406, 454,  410, 454,  432, 1272, 458, 432,  432, 1270,
      434, 454,  436, 424,  436, 1270, 458, 388,  474, 432,  406, 458,
      432, 384,  452, 1296, 434, 1294, 458, 428,  436, 1270, 432, 412,
      476, 1270, 456, 1272, 434, 1292, 462, 1296, 434, 428,  410, 454,
      408, 1320, 434, 428,  432, 432,  408, 1296, 434, 1320, 408, 454,
      410, 454,  434, 428,  408, 454,  436, 1268, 436, 1296, 442, 418,
      464, 384,  450, 1298, 458, 1296, 408, 1296, 462, 424,  434, 428,
      434, 430,  406, 1322, 434, 1270, 460, 384,  452, 412,  474, 430,
      434, 1296, 432, 1272, 436, 1320, 434, 428,  434, 430,  434, 1298,
      430, 1294, 464, 1266,
      410, 10816,
      3516, 1716,
      408, 454,  412, 450,  408, 454,  408, 1322, 432, 430,  434, 1296,
      406, 456,  408, 454,  434, 1296, 408, 454,  434, 430,  408, 452,
      408, 454,  410, 1294, 434, 1296, 460, 428,  436, 1270, 458, 430,
      408, 1296, 462, 1292, 434, 430,  408, 1322, 408, 1322, 434, 430,
      432, 1270, 438, 1322, 406, 1322, 432, 1272, 434, 1294, 436, 1318,
      408, 1324, 406, 1296, 450, 394,  480, 428,  432, 388,  450, 456,
      408, 454,  432, 430,  408, 454,  408, 456,  432, 1274, 486, 1240,
      434, 1296, 436, 1292, 458, 1270, 460, 1268, 462, 1270, 458, 1270,
      438, 450,  434, 430,  434, 428,  410, 452,  434, 430,  434, 384,
      476, 430,  432, 406,
      432, 10822,
      3516, 1690,
      456, 386,  480, 430,  428, 430,  434, 1272, 456, 430,  408, 1296,
      458, 426,  410, 454,  408, 1294, 464, 426,  434, 430,  412, 450,
      436, 428,  406, 1324, 434, 1294, 432, 408,  456, 1272, 458, 384,
      506, 1242, 458, 1272, 458, 430,  434, 428,  432, 1296, 408, 1296,
      458, 1272, 456, 1272, 460, 1292, 434, 1270, 462, 1294, 434, 1298,
      430, 1272, 460, 1294, 406, 454,  434, 430,  432, 430,  432, 430,
      410, 454,  406, 456,  408, 456,  432, 428,  436, 1270, 458, 1296,
      434, 1294, 436, 1294, 406, 1322, 410, 1294, 460, 1294, 432, 1298,
      432, 430,  408, 456,  406, 414,  476, 430,  434, 428,  434, 428,
      436, 426,  410, 454,
      434};  // UNKNOWN 914A12BF * 24C
  const uint8_t expectedState_24C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x18, 0xE7,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_24C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_24C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 24C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_25C[347] = {
      3518, 1690,
      458, 426,  436, 384,  478, 432,  432, 1270, 460, 384,  480, 1268,
      458, 386,  452, 430,  432, 1294, 462, 428,  434, 404,  458, 432,
      432, 428,  436, 1268, 458, 1270, 458, 386,  454, 1294, 486, 360,
      480, 1268, 436, 1296, 460, 1270, 434, 1294, 460, 430,  408, 454,
      436, 1268, 434, 454,  406, 456,  408, 1276, 480, 1268, 460, 428,
      410, 426,  460, 430,  430, 406,  462, 1266, 460, 1274, 430, 456,
      434, 384,  450, 1296, 460, 1268, 434, 1298, 460, 1266, 460, 386,
      510, 350,  452, 1296, 434, 1296, 486, 404,  434, 424,  436, 426,
      434, 432,  430, 1298, 408, 1296, 434, 454,  408, 454,  434, 1270,
      434, 1296, 432, 1296,
      434, 10816,
      3516, 1690,
      458, 426,  408, 458,  432, 388,  476, 1296, 434, 428,  458, 1244,
      462, 430,  406, 430,  460, 1270, 458, 386,  476, 384,  476, 386,
      478, 386,  450, 1296, 460, 1270, 460, 382,  478, 1270, 460, 426,
      410, 1294, 462, 1270, 434, 454,  434, 1270, 432, 1296, 458, 386,
      478, 1294, 432, 1272, 436, 1294, 460, 1272, 432, 1298, 434, 1294,
      462, 1250, 452, 1298, 432, 432,  486, 400,  410, 454,  408, 414,
      476, 430,  430, 386,  476, 404,  460, 428,  410, 1296, 456, 1274,
      432, 1294, 460, 1250, 480, 1268, 436, 1292, 462, 1268, 488, 1242,
      458, 406,  482, 380,  458, 428,  408, 456,  414, 448,  410, 428,
      458, 430,  432, 404,
      434, 10822,
      3516, 1688,
      460, 428,  436, 424,  410, 428,  460, 1270, 460, 428,  410, 1276,
      478, 384,  476, 430,  408, 1296, 460, 432,  414, 418,  436, 454,
      434, 406,  456, 1270, 456, 1270, 462, 428,  408, 1298, 458, 430,
      406, 1296, 460, 1296, 408, 428,  460, 430,  432, 1268, 460, 1270,
      434, 1296, 432, 1294, 460, 1272, 432, 1298, 456, 1272, 460, 1268,
      460, 1270, 458, 1270, 460, 430,  432, 430,  434, 388,  476, 404,
      456, 430,  406, 458,  406, 456,  406, 412,  476, 1270, 460, 1270,
      460, 1270, 460, 1270, 434, 1294, 462, 1268, 460, 1296, 436, 1268,
      460, 428,  432, 430,  432, 430,  408, 440,  448, 388,  450, 452,
      410, 428,  460, 428,
      408};  // UNKNOWN 7A72A3B * 25C
  const uint8_t expectedState_25C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x19, 0xE6,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_25C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_25C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 25C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_26C[347] = {
      3516, 1668,
      480, 402,  458, 386,  504, 380,  458, 1266, 462, 402,  462, 1268,
      460, 402,  462, 402,  458, 1270, 460, 402,  462, 400,  486, 376,
      460, 404,  436, 1292, 460, 1268, 460, 404,  462, 1268, 460, 402,
      458, 1270, 460, 1268, 462, 1266, 436, 1294, 458, 404,  488, 358,
      480, 1268, 460, 402,  488, 374,  458, 1270, 462, 1266, 462, 404,
      462, 400,  460, 404,  486, 376,  460, 1268, 460, 1270, 462, 400,
      458, 404,  458, 1270, 460, 1270, 462, 1266, 462, 400,  460, 1270,
      462, 402,  460, 1268, 462, 1268, 460, 402,  462, 402,  460, 402,
      460, 1270, 460, 402,  460, 1268, 460, 402,  482, 380,  460, 1268,
      490, 1244, 462, 1264,
      460, 10792,
      3518, 1686,
      460, 402,  462, 402,  460, 402,  460, 1270, 470, 388,  466, 1268,
      462, 402,  460, 402,  462, 1266, 462, 402,  460, 402,  460, 384,
      480, 400,  488, 1242, 460, 1268, 462, 402,  462, 1266, 462, 402,
      460, 1270, 460, 1268, 462, 384,  482, 1266, 462, 1266, 462, 402,
      460, 1266, 462, 1270, 460, 1266, 462, 1268, 462, 1268, 460, 1270,
      462, 1268, 458, 1268, 462, 402,  460, 402,  458, 402,  464, 400,
      460, 402,  462, 402,  460, 402,  462, 402,  458, 1270, 462, 1268,
      460, 1268, 462, 1266, 462, 1268, 462, 1268, 458, 1270, 460, 1266,
      462, 402,  516, 346,  460, 404,  460, 402,  488, 376,  458, 404,
      460, 402,  460, 400,
      460, 10794,
      3520, 1684,
      464, 400,  462, 402,  460, 400,  462, 1268, 462, 402,  462, 1270,
      458, 402,  462, 402,  460, 1268, 462, 402,  460, 402,  460, 404,
      460, 402,  462, 1268, 462, 1268, 460, 384,  480, 1266, 462, 404,
      458, 1272, 458, 1268, 462, 402,  460, 402,  460, 1270, 460, 1268,
      462, 1268, 462, 1266, 464, 1266, 462, 1266, 462, 1268, 462, 1268,
      488, 1240, 486, 1242, 466, 400,  462, 402,  460, 400,  460, 404,
      462, 398,  486, 380,  458, 406,  458, 404,  458, 1268, 436, 1292,
      462, 1268, 462, 1268, 460, 1272, 460, 1268, 486, 1242, 460, 1270,
      462, 400,  460, 404,  436, 428,  464, 398,  460, 402,  462, 404,
      458, 404,  458, 404,
      458};  // UNKNOWN 881F925B * 26C
  const uint8_t expectedState_26C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1A, 0xE5,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_26C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_26C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 26C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_30C[347] = {
      3520, 1688,
      462, 400,  460, 404,  460, 404,  456, 1270, 462, 402,  462, 1266,
      490, 374,  464, 398,  462, 1266, 464, 400,  460, 402,  490, 376,
      460, 402,  462, 1248, 478, 1268, 462, 382,  534, 1214, 462, 402,
      458, 1268, 464, 1266, 458, 1270, 462, 1266, 462, 400,  464, 400,
      464, 1264, 462, 406,  456, 402,  460, 1268, 462, 1266, 462, 404,
      460, 402,  462, 400,  462, 404,  458, 1270, 464, 1266, 460, 402,
      462, 402,  434, 1294, 462, 1248, 480, 1270, 490, 372,  462, 1272,
      456, 1268, 464, 1268, 458, 1268, 464, 400,  464, 400,  460, 402,
      462, 1268, 462, 398,  462, 402,  458, 404,  462, 400,  462, 1266,
      438, 1292, 462, 1270,
      460, 10790,
      3520, 1684,
      462, 402,  462, 402,  458, 404,  458, 1272, 462, 400,  460, 1270,
      462, 400,  436, 428,  484, 1244, 462, 380,  482, 402,  486, 376,
      490, 372,  462, 1266, 460, 1270, 462, 402,  460, 1268, 490, 372,
      460, 1270, 460, 1268, 488, 378,  458, 1268, 436, 1296, 488, 374,
      462, 1268, 434, 1292, 462, 1268, 460, 1268, 460, 1270, 436, 1292,
      460, 1268, 462, 1270, 456, 404,  460, 402,  464, 398,  460, 402,
      462, 402,  486, 374,  460, 402,  460, 404,  460, 1270, 460, 1268,
      460, 1268, 462, 1266, 460, 1268, 460, 1268, 462, 1268, 462, 1250,
      504, 376,  462, 400,  436, 428,  458, 404,  460, 400,  462, 406,
      458, 400,  460, 384,
      478, 10796,
      3570, 1632,
      464, 400,  458, 406,  456, 404,  486, 1242, 460, 384,  482, 1264,
      462, 402,  460, 402,  458, 1270, 462, 402,  462, 402,  460, 402,
      462, 400,  490, 1240, 486, 1242, 438, 424,  488, 1242, 462, 402,
      458, 1270, 462, 1266, 464, 400,  460, 404,  462, 1268, 458, 1270,
      462, 1266, 462, 1266, 462, 1270, 460, 1266, 462, 1268, 460, 1268,
      462, 1250, 478, 1268, 464, 400,  462, 404,  458, 400,  488, 378,
      458, 402,  488, 374,  462, 404,  512, 350,  460, 1270, 488, 1242,
      488, 1240, 462, 1266, 464, 1264, 490, 1240, 490, 1240, 462, 1266,
      462, 400,  462, 400,  460, 404,  460, 402,  462, 400,  460, 404,
      458, 382,  480, 402,
      462};  // UNKNOWN B0D0585F * 30C
  const uint8_t expectedState_30C[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1E, 0xE1,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_30C, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_30C, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 30C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));
}

TEST(TestDecodeCoronaAc, RealExample2) {
  IRsendTest irsend(kGpioUnused);
  IRrecv irrecv(kGpioUnused);
  const uint16_t rawData_TOn5[347] = {
      3520, 1684,
      436, 452,  410, 412,  476, 430,  434, 1294, 410, 454,  406, 1296,
      458, 430,  436, 424,  436, 1270, 434, 454,  408, 454,  410, 454,
      434, 428,  434, 1296, 436, 1270, 432, 454,  462, 1268, 434, 386,
      452, 1320, 434, 1270, 434, 1294, 458, 1272, 458, 428,  410, 452,
      436, 1268, 434, 412,  450, 454,  434, 1270, 458, 1274, 456, 388,
      476, 426,  410, 454,  408, 454,  410, 1318, 410, 1296, 458, 430,
      408, 412,  452, 1322, 430, 1298, 434, 1296, 434, 434,  428, 1272,
      458, 1296, 410, 1296, 460, 1294, 432, 430,  408, 452,  434, 430,
      408, 1296, 458, 386,  478, 428,  410, 454,  434, 428,  434, 1272,
      456, 1294, 432, 1272,
      458, 10794,
      3518, 1684,
      464, 426,  410, 454,  488, 374,  434, 1296, 436, 382,  452, 1320,
      436, 428,  406, 454,  410, 1296, 458, 384,  482, 384,  454, 450,
      434, 386,  478, 1268, 460, 1298, 404, 454,  434, 1270, 458, 430,
      410, 1292, 462, 1296, 436, 426,  436, 1270, 434, 1320, 430, 388,
      476, 384,  478, 386,  452, 454,  434, 1294, 412, 452,  432, 1270,
      434, 456,  406, 456,  410, 1292, 460, 1272, 460, 1266, 462, 428,
      434, 1294, 434, 430,  434, 1294, 434, 1272, 460, 1266, 464, 1292,
      438, 426,  434, 428,  408, 432,  460, 1294, 436, 384,  452, 454,
      410, 454,  436, 426,  436, 1270, 458, 1296, 410, 1322, 432, 430,
      434, 1294, 408, 1322,
      436, 10812,
      3478, 1736,
      406, 416,  472, 430,  410, 452,  410, 1322, 408, 454,  436, 1270,
      434, 454,  410, 408,  478, 1268, 460, 430,  434, 428,  408, 454,
      432, 406,  432, 1322, 432, 1296, 434, 430,  408, 1294, 458, 430,
      406, 1322, 434, 1272, 460, 426,  438, 426,  408, 1320, 408, 1296,
      460, 1270, 434, 1296, 434, 1322, 406, 1320, 434, 1252, 476, 1296,
      438, 1268, 432, 1296, 488, 400,  410, 410,  476, 430,  432, 386,
      452, 410,  458, 420,  488, 400,  436, 428,  434, 1294, 408, 1296,
      460, 1294, 410, 1296, 458, 1270, 432, 1298, 432, 1296, 434, 1296,
      460, 428,  408, 452,  462, 402,  432, 430,  406, 430,  438, 450,
      408, 454,  410, 454,
      412};  // UNKNOWN 96CCC404 * On Timer 5H 30C
  const uint8_t expectedState_TOn5[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1E, 0xE1,
      0x28, 0x61, 0x6D, 0x28, 0xD7, 0x23, 0xDC,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_TOn5, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_TOn5,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 30C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: 05:00, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_TOn1[347] = {
      3522, 1684,
      462, 428,  434, 426,  434, 428,  408, 1296, 462, 424,  436, 1266,
      464, 402,  488, 400,  440, 1264, 460, 402,  434, 454,  434, 404,
      460, 404,  460, 1264, 464, 1268, 460, 404,  460, 1266, 462, 404,
      434, 1294, 436, 1292, 464, 1268, 460, 1268, 462, 402,  460, 402,
      458, 1268, 462, 404,  434, 452,  436, 1266, 462, 1268, 462, 402,
      462, 400,  462, 428,  436, 400,  460, 1266, 490, 1240, 492, 372,
      488, 376,  458, 1270, 486, 1242, 464, 1266, 460, 402,  462, 1266,
      464, 1268, 462, 1266, 464, 1270, 462, 396,  464, 400,  460, 402,
      436, 1292, 464, 402,  462, 400,  434, 428,  486, 378,  460, 1266,
      462, 1268, 460, 1266,
      464, 10804,
      3506, 1682,
      462, 402,  462, 400,  460, 428,  438, 1268, 460, 428,  462, 1242,
      460, 428,  436, 400,  462, 1268, 460, 428,  436, 400,  460, 430,
      466, 368,  464, 1266, 438, 1292, 462, 400,  462, 1268, 462, 426,
      410, 1296, 460, 1266, 464, 398,  490, 1242, 488, 1238, 462, 428,
      438, 424,  436, 400,  462, 404,  460, 1266, 462, 404,  460, 404,
      460, 402,  460, 402,  464, 1264, 464, 1264, 464, 1266, 488, 376,
      464, 1266, 458, 1268, 464, 1264, 462, 1266, 466, 1264, 488, 1244,
      462, 1262, 468, 422,  434, 402,  464, 402,  462, 400,  462, 424,
      438, 400,  462, 402,  462, 402,  486, 1242, 460, 1268, 464, 1264,
      436, 1292, 462, 1268,
      460, 10810,
      3504, 1684,
      462, 428,  436, 398,  492, 374,  460, 1268, 462, 404,  462, 1264,
      462, 404,  460, 400,  460, 1266, 490, 400,  438, 424,  438, 400,
      462, 428,  410, 1292, 464, 1268, 460, 428,  460, 1242, 464, 402,
      460, 1266, 460, 1270, 462, 426,  462, 402,  412, 1272, 482, 1266,
      436, 1292, 436, 1294, 462, 1268, 462, 1266, 464, 1264, 464, 1270,
      488, 1238, 464, 1266, 464, 396,  464, 426,  438, 402,  458, 402,
      464, 398,  462, 430,  408, 426,  460, 428,  492, 1210, 440, 1292,
      464, 1266, 438, 1292, 460, 1266, 464, 1266, 464, 1268, 460, 1266,
      438, 430,  458, 402,  458, 406,  460, 406,  456, 400,  434, 426,
      464, 400,  460, 402,
      462};  // UNKNOWN 446E2F48 * On Timer 1H 30C
  const uint8_t expectedState_TOn1[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1E, 0xE1,
      0x28, 0x61, 0x6D, 0x08, 0xF7, 0x07, 0xF8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_TOn1, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_TOn1,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 30C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: 01:00, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_TOn2[347] = {
      3516, 1716,
      410, 452,  408, 454,  412, 450,  434, 1270, 460, 430,  432, 1272,
      456, 406,  460, 384,  452, 1298, 458, 428,  406, 456,  436, 428,
      434, 430,  432, 1298, 434, 1298, 408, 428,  458, 1298, 432, 430,
      434, 1294, 434, 1296, 432, 1272, 458, 1296, 408, 454,  436, 428,
      436, 1268, 458, 430,  436, 428,  434, 1272, 432, 1320, 460, 402,
      410, 454,  432, 388,  474, 388,  452, 1296, 460, 1270, 458, 386,
      450, 412,  478, 1296, 430, 1272, 458, 1298, 434, 428,  434, 1254,
      474, 1296, 410, 1320, 434, 1270, 460, 384,  478, 428,  434, 428,
      434, 1272, 460, 384,  478, 428,  432, 430,  434, 428,  410, 1296,
      458, 1274, 454, 1270,
      460, 10810,
      3500, 1716,
      432, 430,  408, 452,  434, 430,  410, 1294, 456, 428,  434, 1298,
      408, 432,  544, 314,  462, 1270, 430, 454,  436, 430,  458, 404,
      432, 386,  478, 1268, 460, 1270, 458, 388,  450, 1322, 430, 434,
      458, 1268, 434, 1294, 410, 454,  434, 1270, 460, 1294, 432, 430,
      410, 454,  434, 428,  406, 456,  432, 430,  408, 1320, 408, 456,
      432, 430,  434, 428,  410, 1294, 434, 1294, 486, 1268, 432, 1272,
      460, 426,  414, 1292, 462, 1294, 432, 1298, 430, 388,  478, 1296,
      408, 1296, 458, 1270, 458, 386,  452, 456,  408, 454,  436, 426,
      434, 1272, 432, 430,  458, 430,  434, 430,  406, 1320, 436, 1294,
      434, 1296, 410, 1320,
      434, 10812,
      3504, 1686,
      432, 452,  434, 430,  436, 428,  406, 1296, 460, 404,  460, 1292,
      436, 428,  436, 428,  436, 1268, 436, 454,  412, 452,  408, 454,
      434, 428,  408, 1296, 462, 1266, 462, 384,  480, 1266, 458, 430,
      410, 1320, 434, 1270, 434, 428,  436, 452,  412, 1294, 432, 1320,
      432, 1274, 458, 1270, 434, 1294, 460, 1270, 460, 1296, 434, 1268,
      436, 1294, 434, 1296, 460, 430,  434, 424,  436, 428,  434, 426,
      410, 410,  478, 430,  432, 408,  456, 428,  408, 1298, 458, 1268,
      436, 1296, 460, 1292, 462, 1268, 436, 1270, 460, 1294, 434, 1294,
      436, 402,  488, 400,  408, 456,  432, 386,  478, 428,  408, 452,
      408, 456,  410, 454,
      406};  // UNKNOWN D49AF170 * On Timer 2H 30C
  const uint8_t expectedState_TOn2[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1E, 0xE1,
      0x28, 0x61, 0x6D, 0x10, 0xEF, 0x0E, 0xF1,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_TOn2, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_TOn2,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 30C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: 02:00, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_21C2[347] = {
      3522, 1682,
      438, 426,  460, 402,  462, 402,  434, 1296, 434, 426,  460, 1270,
      436, 430,  460, 400,  436, 1294, 462, 398,  436, 428,  462, 400,
      462, 400,  438, 1292, 460, 1270, 460, 404,  434, 1294, 462, 402,
      462, 1268, 434, 1294, 462, 1268, 490, 1240, 462, 400,  460, 404,
      460, 1268, 436, 426,  462, 402,  462, 1266, 460, 1268, 438, 428,
      458, 404,  460, 402,  462, 398,  462, 1272, 460, 1266, 462, 404,
      458, 402,  436, 1294, 460, 1268, 436, 1292, 464, 1266, 436, 428,
      462, 1268, 462, 400,  438, 1290, 460, 404,  460, 402,  462, 404,
      434, 424,  462, 1268, 436, 426,  462, 1272, 456, 404,  460, 1270,
      434, 1292, 438, 1292,
      462, 10786,
      3498, 1714,
      458, 404,  458, 402,  462, 400,  464, 1264, 466, 398,  462, 1266,
      438, 428,  436, 424,  462, 1266, 490, 374,  436, 424,  436, 428,
      434, 426,  464, 1266, 464, 1268, 434, 428,  462, 1266, 466, 396,
      436, 1294, 462, 1270, 460, 402,  460, 1266, 462, 1268, 460, 404,
      458, 1270, 434, 1294, 460, 1268, 464, 1266, 462, 1266, 464, 1266,
      462, 1268, 462, 1266, 464, 400,  434, 426,  438, 426,  460, 402,
      436, 426,  464, 400,  470, 370,  486, 398,  464, 1264, 440, 1292,
      462, 1266, 464, 1266, 464, 1266, 462, 1266, 462, 1268, 460, 1270,
      462, 398,  462, 400,  438, 426,  462, 400,  462, 402,  434, 430,
      458, 402,  460, 400,
      436, 10820,
      3496, 1708,
      462, 402,  464, 400,  438, 422,  438, 1294, 460, 400,  462, 1266,
      464, 400,  462, 400,  464, 1266, 462, 402,  436, 426,  460, 404,
      436, 426,  462, 1266, 436, 1294, 462, 400,  462, 1266, 462, 400,
      460, 1268, 464, 1266, 462, 402,  436, 426,  436, 1294, 436, 1294,
      438, 1290, 462, 1268, 462, 1266, 436, 1292, 462, 1268, 460, 1248,
      482, 1268, 462, 1270, 458, 404,  434, 426,  464, 400,  460, 406,
      434, 426,  462, 402,  460, 384,  480, 400,  436, 1294, 460, 1268,
      492, 1238, 462, 1268, 460, 1272, 434, 1292, 462, 1266, 438, 1292,
      464, 400,  462, 400,  436, 426,  438, 424,  488, 374,  462, 402,
      462, 400,  464, 400,
      438};  // UNKNOWN D1869C5B * 21C
  const uint8_t expectedState_21C2[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x15, 0xEA,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_21C2, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_21C2,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 21C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_20C2[347] = {
      3498, 1708,
      436, 430,  434, 426,  464, 398,  460, 1268, 456, 388,  482, 1266,
      436, 426,  436, 426,  438, 1292, 436, 426,  436, 428,  436, 424,
      460, 404,  436, 1290, 438, 1292, 462, 404,  434, 1292, 438, 426,
      462, 1266, 516, 1212, 438, 1292, 436, 1292, 438, 424,  438, 424,
      462, 1268, 438, 424,  436, 426,  438, 1292, 460, 1268, 460, 402,
      436, 428,  436, 426,  438, 426,  434, 1294, 436, 1294, 436, 428,
      436, 426,  464, 1264, 436, 1274, 484, 1264, 440, 424,  460, 402,
      438, 1292, 434, 426,  438, 1292, 436, 428,  436, 426,  464, 398,
      492, 1238, 438, 1292, 436, 428,  460, 1248, 456, 426,  438, 1294,
      434, 1296, 434, 1296,
      434, 10812,
      3498, 1710,
      436, 428,  434, 426,  438, 424,  438, 1294, 438, 424,  438, 1292,
      434, 426,  442, 420,  438, 1290, 438, 426,  466, 396,  462, 400,
      436, 428,  436, 1294, 438, 1290, 466, 398,  436, 1294, 436, 426,
      460, 1268, 462, 1268, 436, 426,  438, 1290, 438, 1294, 462, 402,
      462, 1266, 462, 1266, 462, 1266, 436, 1294, 440, 1290, 464, 1266,
      436, 1292, 436, 1294, 436, 426,  462, 400,  438, 424,  436, 426,
      462, 400,  438, 426,  462, 400,  436, 426,  438, 1292, 438, 1292,
      438, 1292, 462, 1266, 438, 1270, 458, 1292, 438, 1294, 462, 1266,
      438, 428,  434, 426,  464, 398,  436, 426,  436, 428,  436, 426,
      492, 370,  438, 426,
      436, 10818,
      3492, 1712,
      462, 402,  460, 402,  438, 426,  440, 1292, 436, 424,  464, 1266,
      438, 424,  462, 400,  438, 1288, 438, 428,  434, 428,  486, 376,
      462, 402,  434, 1292, 436, 1292, 438, 424,  462, 1268, 436, 426,
      438, 1294, 462, 1266, 436, 428,  436, 424,  438, 1292, 438, 1290,
      440, 1292, 434, 1294, 436, 1294, 436, 1294, 514, 1212, 438, 1292,
      436, 1296, 458, 1268, 438, 424,  460, 404,  460, 400,  462, 400,
      462, 400,  438, 426,  434, 430,  434, 426,  466, 1266, 464, 1262,
      436, 1294, 434, 1294, 464, 1266, 464, 1264, 460, 1268, 464, 1266,
      462, 404,  460, 402,  436, 428,  434, 428,  436, 428,  462, 400,
      462, 400,  462, 400,
      464};  // UNKNOWN 27CBC9D7 * 20C
  const uint8_t expectedState_20C2[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x14, 0xEB,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_20C2, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_20C2,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 20C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_Off2[347] = {
      3522, 1684,
      436, 428,  460, 404,  436, 424,  464, 1266, 436, 426,  462, 1270,
      452, 390,  480, 404,  462, 1268, 436, 424,  462, 402,  462, 400,
      434, 428,  436, 1292, 462, 1268, 462, 402,  460, 1268, 460, 402,
      436, 1292, 462, 1266, 436, 1294, 438, 1292, 436, 426,  460, 402,
      462, 1268, 438, 424,  462, 400,  462, 1270, 458, 1270, 436, 428,
      458, 404,  460, 400,  436, 426,  464, 1268, 460, 1266, 464, 398,
      464, 398,  462, 1270, 434, 1292, 438, 1292, 460, 404,  436, 1296,
      458, 402,  462, 402,  460, 404,  460, 1268, 460, 402,  436, 426,
      434, 1274, 482, 400,  438, 1292, 490, 1240, 462, 1268, 460, 402,
      436, 1292, 438, 1294,
      460, 10808,
      3474, 1692,
      482, 400,  462, 402,  460, 402,  460, 1268, 464, 400,  488, 1240,
      462, 400,  462, 402,  460, 1270, 434, 426,  462, 402,  462, 402,
      462, 400,  462, 1268, 462, 1266, 462, 400,  436, 1294, 460, 402,
      436, 1292, 438, 1292, 436, 428,  460, 1268, 462, 1268, 436, 428,
      438, 1290, 466, 1266, 462, 1266, 464, 1266, 460, 1268, 462, 1268,
      436, 1292, 462, 1266, 452, 390,  482, 400,  436, 428,  462, 400,
      464, 400,  462, 402,  434, 428,  460, 402,  462, 1266, 462, 1266,
      462, 1270, 436, 1294, 460, 1268, 460, 1268, 438, 1296, 432, 1294,
      464, 398,  462, 402,  434, 430,  460, 400,  462, 400,  460, 402,
      460, 402,  438, 426,
      436, 10816,
      3522, 1686,
      436, 428,  434, 426,  464, 400,  460, 1270, 460, 400,  438, 1294,
      460, 400,  464, 400,  438, 1296, 436, 424,  460, 402,  460, 402,
      464, 400,  462, 1266, 438, 1292, 462, 402,  434, 1296, 432, 428,
      460, 1270, 462, 1266, 436, 428,  436, 428,  458, 1268, 438, 1290,
      438, 1292, 460, 1270, 434, 1294, 460, 1268, 462, 1246, 456, 1294,
      438, 1290, 460, 1268, 446, 388,  490, 400,  436, 426,  462, 400,
      438, 424,  462, 402,  436, 428,  434, 430,  460, 1270, 458, 1266,
      462, 1268, 438, 1292, 438, 1290, 436, 1294, 462, 1268, 462, 1266,
      460, 404,  434, 428,  460, 400,  462, 402,  436, 426,  434, 428,
      434, 426,  438, 430,
      458};  // UNKNOWN FBD27697 * OFF
  const uint8_t expectedState_Off2[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x22, 0xDD,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_Off2, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_Off2,
                  irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: Off, Power Button: On, Mode: 0 (Heat), Temp: 18C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));


  const uint16_t rawData_U[347] = {
      3520, 1686,
      462, 402,  460, 402,  462, 402,  436, 1276, 478, 402,  462, 1266,
      464, 400,  460, 402,  462, 1268, 452, 392,  478, 402,  464, 380,
      480, 404,  432, 1296, 462, 1266, 460, 404,  460, 1270, 460, 402,
      460, 1270, 458, 1270, 460, 1270, 456, 1270, 462, 402,  460, 402,
      460, 1270, 460, 400,  464, 400,  460, 1268, 464, 1264, 462, 404,
      458, 402,  434, 428,  464, 402,  456, 1270, 462, 1270, 460, 404,
      458, 402,  438, 1292, 460, 1268, 464, 1266, 464, 1264, 462, 404,
      458, 1272, 458, 1270, 460, 1268, 464, 402,  458, 402,  462, 400,
      462, 400,  462, 1270, 458, 406,  430, 430,  458, 400,  462, 1270,
      460, 1266, 464, 1266,
      462, 10790,
      3520, 1682,
      462, 404,  434, 428,  464, 400,  460, 1270, 460, 400,  464, 1266,
      462, 404,  460, 402,  464, 1264, 460, 406,  460, 402,  458, 406,
      460, 402,  458, 1270, 464, 1266, 460, 404,  460, 1270, 462, 402,
      488, 1240, 460, 1268, 462, 400,  462, 1268, 462, 1266, 462, 400,
      462, 1268, 460, 1250, 482, 1266, 462, 1270, 462, 1266, 462, 1268,
      458, 1270, 462, 1268, 460, 400,  462, 402,  460, 400,  462, 402,
      462, 398,  462, 404,  486, 374,  460, 404,  458, 1270, 460, 1270,
      486, 1244, 458, 1270, 464, 1266, 460, 1268, 462, 1268, 460, 1270,
      462, 400,  460, 406,  458, 402,  462, 400,  462, 404,  458, 400,
      516, 350,  458, 402,
      462, 10794,
      3520, 1684,
      460, 402,  460, 402,  460, 406,  460, 1268, 458, 406,  458, 1268,
      462, 400,  464, 400,  460, 1268, 462, 402,  460, 402,  464, 426,
      436, 400,  462, 1264, 462, 1270, 460, 402,  460, 1266, 464, 400,
      460, 1268, 464, 1266, 460, 406,  456, 404,  462, 1268, 462, 1268,
      460, 1266, 490, 1240, 464, 1266, 460, 1270, 438, 1294, 460, 1250,
      478, 1266, 462, 1270, 460, 404,  462, 400,  462, 400,  462, 402,
      462, 398,  460, 404,  460, 402,  460, 402,  460, 1268, 460, 1270,
      460, 1272, 458, 1270, 460, 1268, 464, 1268, 434, 1296, 462, 1266,
      464, 398,  462, 402,  434, 426,  462, 404,  460, 402,  462, 404,
      456, 406,  460, 400,
      462};  // UNKNOWN 2D1BA8F7 * unk
  const uint8_t expectedState_U[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_U, 347, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_U, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 29C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));
}

TEST(TestDecodeCoronaAc, RealExampleShort) {
  IRsendTest irsend(kGpioUnused);
  IRrecv irrecv(kGpioUnused);
  const uint16_t rawData_A1[115] = {
      3548, 1658,
      462, 400,  464, 424,  436, 428,  436, 1272, 460, 400,  462, 1266,
      464, 426,  436, 426,  434, 1270, 432, 454,  436, 402,  460, 384,
      482, 400,  486, 1244, 460, 1268, 462, 404,  484, 1242, 460, 428,
      460, 1250, 430, 1292, 462, 1266, 464, 404,  456, 384,  480, 1266,
      462, 428,  436, 1270, 460, 1268, 462, 428,  434, 1270, 460, 430,
      434, 404,  460, 1294, 460, 1242, 462, 382,  478, 428,  436, 1268,
      458, 406,  460, 1268, 460, 1268, 460, 404,  458, 404,  434, 430,
      462, 426,  434, 430,  432, 1268, 462, 426,  436, 402,  460, 404,
      458, 1268, 464, 1270, 432, 1294, 464, 1266, 458, 404,  462, 1268,
      460, 1268, 464, 1266,
      462};  // UNKNOWN AEDD5409 * Auto1
  const uint8_t expectedState_A1[kCoronaAcStateLengthShort] = {
      0x28, 0x61, 0x9D, 0x96, 0x69, 0x10, 0xEF};
  irsend.begin();
  irsend.reset();
  irsend.sendRaw(rawData_A1, 115, 38);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBitsShort, irsend.capture.bits);
  EXPECT_STATE_EQ(expectedState_A1, irsend.capture.state, irsend.capture.bits);
  // this is special, but showing what it might be
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 16C, "
      "Fan: 2 (Medium), Swing(V) Toggle: Off, Econo: Off, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));
}

TEST(TestDecodeCoronaAc, SyntheticExample1) {
  IRsendTest irsend(kGpioUnused);
  IRrecv irrecv(kGpioUnused);
  irsend.begin();
  irsend.reset();
  const uint8_t state[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(state);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  EXPECT_EQ(kCoronaAcBits, irsend.capture.bits);
  EXPECT_STATE_EQ(state, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 29C, "
      "Fan: 1 (Low), Swing(V) Toggle: Off, Econo: On, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));

  EXPECT_EQ(
    "f38000d50"
    "m3500s1680"
    "m450s420m450s420m450s420m450s1270m450s420m450s1270m450s420m450s420"
    "m450s1270m450s420m450s420m450s420m450s420m450s1270m450s1270m450s420"
    "m450s1270m450s420m450s1270m450s1270m450s1270m450s1270m450s420m450s420"
    "m450s1270m450s420m450s420m450s1270m450s1270m450s420m450s420m450s420"
    "m450s420m450s1270m450s1270m450s420m450s420m450s1270m450s1270m450s1270"
    "m450s1270m450s420m450s1270m450s1270m450s1270m450s420m450s420m450s420"
    "m450s420m450s1270m450s420m450s420m450s420m450s1270m450s1270m450s1270"
    "m450s10800"
    "m3500s1680"
    "m450s420m450s420m450s420m450s1270m450s420m450s1270m450s420m450s420"
    "m450s1270m450s420m450s420m450s420m450s420m450s1270m450s1270m450s420"
    "m450s1270m450s420m450s1270m450s1270m450s420m450s1270m450s1270m450s420"
    "m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270"
    "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420"
    "m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270"
    "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420"
    "m450s10800"
    "m3500s1680"
    "m450s420m450s420m450s420m450s1270m450s420m450s1270m450s420m450s420"
    "m450s1270m450s420m450s420m450s420m450s420m450s1270m450s1270m450s420"
    "m450s1270m450s420m450s1270m450s1270m450s420m450s420m450s1270m450s1270"
    "m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270"
    "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420"
    "m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270m450s1270"
    "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420"
    "m450s10800",
    irsend.outputStr());

  irsend.reset();
  const uint8_t stateShort[kCoronaAcStateLengthShort] = {
      0x28, 0x61, 0x9D, 0x96, 0x69, 0x10, 0xEF};
  irsend.sendCoronaAc(stateShort, kCoronaAcStateLengthShort);
  irsend.makeDecodeResult();

  ASSERT_TRUE(irrecv.decode(&irsend.capture));
  ASSERT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);
  ASSERT_EQ(kCoronaAcBitsShort, irsend.capture.bits);
  EXPECT_STATE_EQ(stateShort, irsend.capture.state, irsend.capture.bits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 0 (Heat), Temp: 16C, "
      "Fan: 2 (Medium), Swing(V) Toggle: Off, Econo: Off, "
      "On Timer: Off, Off Timer: Off",
      IRAcUtils::resultAcToString(&irsend.capture));

  EXPECT_EQ(
      "f38000d50"
      "m3500s1680"
      "m450s420m450s420m450s420m450s1270m450s420m450s1270m450s420m450s420"
      "m450s1270m450s420m450s420m450s420m450s420m450s1270m450s1270m450s420"
      "m450s1270m450s420m450s1270m450s1270m450s1270m450s420m450s420m450s1270"
      "m450s420m450s1270m450s1270m450s420m450s1270m450s420m450s420m450s1270"
      "m450s1270m450s420m450s420m450s1270m450s420m450s1270m450s1270m450s420"
      "m450s420m450s420m450s420m450s420m450s1270m450s420m450s420m450s420"
      "m450s1270m450s1270m450s1270m450s1270m450s420m450s1270m450s1270m450s1270"
      "m450s10800",
      irsend.outputStr());
}

TEST(TestDecodeCoronaAc, SyntheticExampleNonMatch) {
  IRsendTest irsend(kGpioUnused);
  IRrecv irrecv(kGpioUnused);

  // Test checksum and prefix
  // first base example match
  irsend.begin();
  irsend.reset();
  const uint8_t stateOk[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateOk);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_EQ(decode_type_t::CORONA_AC, irsend.capture.decode_type);

  irsend.begin();
  irsend.reset();
  // non valid Corona header section 1
  const uint8_t stateHeaderFail1[kCoronaAcStateLength] = {
      0x00, 0x61, 0x3D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateHeaderFail1);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_NE(decode_type_t::CORONA_AC, irsend.capture.decode_type);

  irsend.begin();
  irsend.reset();
  // non valid Corona header section 1 b2
  const uint8_t stateHeaderFail12[kCoronaAcStateLength] = {
      0x28, 0x00, 0x3D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateHeaderFail12);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_NE(decode_type_t::CORONA_AC, irsend.capture.decode_type);

  irsend.begin();
  irsend.reset();
  // non valid Corona section number
  const uint8_t stateSection1NumFail[kCoronaAcStateLength] = {
      0x28, 0x61, 0x2D, 0x19, 0xE6, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateSection1NumFail);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_NE(decode_type_t::CORONA_AC, irsend.capture.decode_type);

  irsend.begin();
  irsend.reset();
  // non valid Corona invert D0
  const uint8_t stateInvertD0Fail[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0x19, 0x1D, 0xE2,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateInvertD0Fail);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_NE(decode_type_t::CORONA_AC, irsend.capture.decode_type);

  irsend.begin();
  irsend.reset();
  // non valid Corona invert D1
  const uint8_t stateInvertD1Fail[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x19, 0xE6, 0x1D, 0x1D,
      0x28, 0x61, 0x6D, 0xE8, 0x17, 0x17, 0xE8,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  irsend.sendCoronaAc(stateInvertD1Fail);
  irsend.makeDecodeResult();

  EXPECT_TRUE(irrecv.decode(&irsend.capture));
  EXPECT_NE(decode_type_t::CORONA_AC, irsend.capture.decode_type);
}

TEST(TestUtils, Housekeeping) {
  ASSERT_EQ("CORONA_AC", typeToString(decode_type_t::CORONA_AC));
  ASSERT_EQ(decode_type_t::CORONA_AC, strToDecodeType("CORONA_AC"));
  ASSERT_TRUE(hasACState(decode_type_t::CORONA_AC));
  ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::CORONA_AC));
  ASSERT_EQ(kCoronaAcBits, IRsend::defaultBits(decode_type_t::CORONA_AC));
  ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::CORONA_AC));
  ASSERT_EQ(kCoronaAcStateLength, 7 * 3);
  ASSERT_EQ(kCoronaAcStateLengthShort, 7);
  ASSERT_EQ(kCoronaAcSectionBytes, 7);
  ASSERT_EQ(kCoronaAcSections, 3);
}

// Tests for IRCoronaAc class.

TEST(TestCoronaAcClass, Power) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();

  ac.on();
  EXPECT_TRUE(ac.getPower());
  EXPECT_TRUE(ac.getPowerButton());

  ac.off();
  EXPECT_FALSE(ac.getPower());
  EXPECT_TRUE(ac.getPowerButton());

  ac.setOnTimer(60);
  EXPECT_FALSE(ac.getPowerButton());
  ac.setPower(true);
  EXPECT_TRUE(ac.getPower());
  EXPECT_EQ(0, ac.getOnTimer());
  EXPECT_FALSE(ac.getPowerButton());

  ac.setOffTimer(60);
  EXPECT_FALSE(ac.getPowerButton());
  ac.setPower(false);
  EXPECT_FALSE(ac.getPower());
  EXPECT_EQ(0, ac.getOffTimer());
  EXPECT_FALSE(ac.getPowerButton());
}

TEST(TestCoronaAcClass, Temperature) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();

  ac.setTemp(0);
  EXPECT_EQ(kCoronaAcMinTemp, ac.getTemp());

  ac.setTemp(255);
  EXPECT_EQ(kCoronaAcMaxTemp, ac.getTemp());

  ac.setTemp(kCoronaAcMinTemp);
  EXPECT_EQ(kCoronaAcMinTemp, ac.getTemp());

  ac.setTemp(kCoronaAcMaxTemp);
  EXPECT_EQ(kCoronaAcMaxTemp, ac.getTemp());

  ac.setTemp(kCoronaAcMinTemp - 1);
  EXPECT_EQ(kCoronaAcMinTemp, ac.getTemp());

  ac.setTemp(kCoronaAcMaxTemp + 1);
  EXPECT_EQ(kCoronaAcMaxTemp, ac.getTemp());

  ac.setTemp(17);
  EXPECT_EQ(17, ac.getTemp());

  ac.setTemp(21);
  EXPECT_EQ(21, ac.getTemp());

  ac.setTemp(25);
  EXPECT_EQ(25, ac.getTemp());

  ac.setTemp(29);
  EXPECT_EQ(29, ac.getTemp());
}

TEST(TestCoronaAcClass, OperatingMode) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();

  ac.setMode(kCoronaAcModeCool);
  EXPECT_EQ(kCoronaAcModeCool, ac.getMode());

  ac.setMode(kCoronaAcModeFan);
  EXPECT_EQ(kCoronaAcModeFan, ac.getMode());

  ac.setMode(kCoronaAcModeHeat);
  EXPECT_EQ(kCoronaAcModeHeat, ac.getMode());

  ac.setMode(kCoronaAcModeFan + 1);
  EXPECT_EQ(kCoronaAcModeCool, ac.getMode());

  ac.setMode(255);
  EXPECT_EQ(kCoronaAcModeCool, ac.getMode());
  ac.setMode(0);
  EXPECT_EQ(kCoronaAcModeHeat, ac.getMode());
}

TEST(TestCoronaAcClass, EconoPowerSave) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();
  ac.setEcono(true);
  EXPECT_TRUE(ac.getEcono());
  ac.setEcono(false);
  EXPECT_FALSE(ac.getEcono());
  ac.setEcono(true);
  EXPECT_TRUE(ac.getEcono());
}

TEST(TestCoronaAcClass, SwingVerticalToggle) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();
  ac.setSwingVToggle(true);
  EXPECT_TRUE(ac.getSwingVToggle());
  ac.setSwingVToggle(false);
  EXPECT_FALSE(ac.getSwingVToggle());
  ac.setSwingVToggle(true);
  EXPECT_TRUE(ac.getSwingVToggle());
}

TEST(TestCoronaAcClass, Timer) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();
  ac.setPowerButton(false);
  ac.setMode(kCoronaAcModeHeat);
  const uint8_t expectedStateNoTimer[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x10, 0xEF, 0x01, 0xFE,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  ASSERT_FALSE(ac.getPower());
  ASSERT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateNoTimer, ac.getRaw(), kCoronaAcBits);

  ac.setOnTimer(3 * 60);
  EXPECT_EQ(3 * 60, ac.getOnTimer());
  const uint8_t expectedStateOnTimer3H[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x10, 0xEF, 0x11, 0xEE,
      0x28, 0x61, 0x6D, 0x18, 0xE7, 0x15, 0xEA,  // 5400
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  ASSERT_TRUE(ac.getPower());  // remote should be on from timer
  ASSERT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateOnTimer3H, ac.getRaw(), kCoronaAcBits);

  ac.setOnTimer(0);
  EXPECT_EQ(0, ac.getOnTimer());
  ASSERT_FALSE(ac.getPowerButton());
  ASSERT_TRUE(ac.getPower());  // remote should still be on
  ac.off();  // set it to off
  EXPECT_STATE_EQ(expectedStateNoTimer, ac.getRaw(), kCoronaAcBits);
  ac.setOnTimer(kCoronaAcTimerOff);
  EXPECT_EQ(0, ac.getOnTimer());
  EXPECT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateNoTimer, ac.getRaw(), kCoronaAcBits);

  ac.setOffTimer(1);
  EXPECT_EQ(1, ac.getOffTimer());
  ASSERT_TRUE(ac.getPower());  // remote should be on from timer
  const uint8_t expectedStateOffTimer1m[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x10, 0xEF, 0x11, 0xEE,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0x1E, 0xE1, 0x00, 0xFF};  // 30
  ASSERT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateOffTimer1m, ac.getRaw(), kCoronaAcBits);

  ac.setOnTimer(2);
  EXPECT_EQ(2, ac.getOnTimer());
  ASSERT_TRUE(ac.getPower());  // remote should be on from timer
  // setting any of the timers needs to reset the other one
  ASSERT_EQ(0, ac.getOffTimer());
  const uint8_t expectedStateOnTimer2m[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x10, 0xEF, 0x11, 0xEE,
      0x28, 0x61, 0x6D, 0x3C, 0xC3, 0x00, 0xFF,  // 60
      0x28, 0x61, 0xCD, 0xFF, 0x00, 0xFF, 0x00};
  ASSERT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateOnTimer2m, ac.getRaw(), kCoronaAcBits);

  // setting a higher value than max should instead disable
  ac.setOnTimer(kCoronaAcTimerMax + 1);
  ASSERT_EQ(0, ac.getOnTimer());
  ASSERT_FALSE(ac.getPowerButton());
  ASSERT_TRUE(ac.getPower());  // remote should still be on
  ac.off();
  ASSERT_FALSE(ac.getPowerButton());
  EXPECT_STATE_EQ(expectedStateNoTimer, ac.getRaw(), kCoronaAcBits);
}


TEST(TestCoronaAcClass, FanSpeed) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();

  // Unexpected value should default to Auto.
  ac.setFan(255);
  EXPECT_EQ(kCoronaAcFanAuto, ac.getFan());
  ac.setFan(5);
  EXPECT_EQ(kCoronaAcFanAuto, ac.getFan());

  ac.setFan(kCoronaAcFanHigh);
  EXPECT_EQ(kCoronaAcFanHigh, ac.getFan());

  // Beyond High should default to Auto.
  ac.setFan(kCoronaAcFanHigh + 1);
  EXPECT_EQ(kCoronaAcFanAuto, ac.getFan());

  ac.setFan(kCoronaAcFanMedium);
  EXPECT_EQ(kCoronaAcFanMedium, ac.getFan());

  ac.setFan(kCoronaAcFanLow);
  EXPECT_EQ(kCoronaAcFanLow, ac.getFan());

  ac.setFan(kCoronaAcFanAuto);
  EXPECT_EQ(kCoronaAcFanAuto, ac.getFan());
}

// Test human readable output.
TEST(TestCoronaAcClass, HumanReadable) {
  IRCoronaAc ac(kGpioUnused);
  EXPECT_EQ(
      "Power: Off, Power Button: On, Mode: 2 (Cool), Temp: 17C, "
      "Fan: 0 (Auto), Swing(V) Toggle: Off, Econo: Off, "
      "On Timer: Off, Off Timer: Off",
      ac.toString());
  ac.setPower(true);
  ac.setMode(kCoronaAcModeFan);
  ac.setTemp(30);
  ac.setFan(kCoronaAcFanAuto);
  ac.setSwingVToggle(true);
  EXPECT_EQ(
      "Power: On, Power Button: On, Mode: 3 (Fan), Temp: 30C, "
      "Fan: 0 (Auto), Swing(V) Toggle: On, Econo: Off, "
      "On Timer: Off, Off Timer: Off",
      ac.toString());
  ac.setOffTimer(8 * 60 + 37);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 3 (Fan), Temp: 30C, "
      "Fan: 0 (Auto), Swing(V) Toggle: On, Econo: Off, "
      "On Timer: Off, Off Timer: 08:37",
      ac.toString());
  ac.setOnTimer(5 * 60 + 59);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 3 (Fan), Temp: 30C, "
      "Fan: 0 (Auto), Swing(V) Toggle: On, Econo: Off, "
      "On Timer: 05:59, Off Timer: Off",
      ac.toString());
  ac.setOnTimer(59);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 3 (Fan), Temp: 30C, "
      "Fan: 0 (Auto), Swing(V) Toggle: On, Econo: Off, "
      "On Timer: 00:59, Off Timer: Off",
      ac.toString());
  ac.setEcono(true);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 3 (Fan), Temp: 30C, "
      "Fan: 0 (Auto), Swing(V) Toggle: On, Econo: On, "
      "On Timer: 00:59, Off Timer: Off",
      ac.toString());
}

TEST(TestCoronaAcClass, ReconstructKnownState) {
  IRCoronaAc ac(kGpioUnused);
  const uint8_t expectedState[kCoronaAcStateLength] = {
      0x28, 0x61, 0x3D, 0x59, 0xA6, 0xD3, 0x2C,
      0x28, 0x61, 0x6D, 0xFF, 0x00, 0xFF, 0x00,
      0x28, 0x61, 0xCD, 0x18, 0xE7, 0x15, 0xEA};
  ASSERT_TRUE(IRCoronaAc::validSection(expectedState,
      0 * kCoronaAcSectionBytes, 0));
  ASSERT_TRUE(IRCoronaAc::validSection(expectedState,
      1 * kCoronaAcSectionBytes, 1));
  ASSERT_TRUE(IRCoronaAc::validSection(expectedState,
      2 * kCoronaAcSectionBytes, 2));
  ac.begin();
  ac.stateReset();
  // ASSERT_STATE_NE(expectedState, ac.getRaw());
  ac.on();
  ac.setMode(kCoronaAcModeFan);
  ac.setTemp(19);
  ac.setFan(kCoronaAcFanLow);
  ac.setSwingVToggle(true);
  ac.setOffTimer(3 * 60);
  ac.setEcono(true);
  EXPECT_STATE_EQ(expectedState, ac.getRaw(), kCoronaAcBits);
  EXPECT_EQ(
      "Power: On, Power Button: Off, Mode: 3 (Fan), Temp: 19C, "
      "Fan: 1 (Low), Swing(V) Toggle: On, Econo: On, "
      "On Timer: Off, Off Timer: 03:00",
      ac.toString());
}

TEST(TestCoronaAcClass, toCommon) {
  IRCoronaAc ac(kGpioUnused);
  ac.begin();
  ac.stateReset();
  ac.on();
  ac.setMode(kCoronaAcModeFan);
  ac.setTemp(20);
  ac.setFan(kCoronaAcFanLow);
  ac.setSwingVToggle(true);
  ac.setOffTimer(3 * 60);
  ac.setEcono(true);
  // Now test it.
  ASSERT_EQ(decode_type_t::CORONA_AC, ac.toCommon().protocol);
  ASSERT_EQ(-1, ac.toCommon().model);
  ASSERT_TRUE(ac.toCommon().power);
  ASSERT_TRUE(ac.toCommon().celsius);
  ASSERT_EQ(20, ac.toCommon().degrees);
  ASSERT_EQ(stdAc::opmode_t::kFan, ac.toCommon().mode);
  ASSERT_EQ(stdAc::fanspeed_t::kLow, ac.toCommon().fanspeed);
  ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
  ASSERT_TRUE(ac.toCommon().econo);
  // Unsupported.
  ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh);
  ASSERT_FALSE(ac.toCommon().turbo);
  ASSERT_FALSE(ac.toCommon().quiet);
  ASSERT_FALSE(ac.toCommon().clean);
  ASSERT_FALSE(ac.toCommon().light);
  ASSERT_FALSE(ac.toCommon().filter);
  ASSERT_FALSE(ac.toCommon().beep);
  ASSERT_EQ(-1, ac.toCommon().sleep);
  ASSERT_EQ(-1, ac.toCommon().clock);
}
